#ifndef FHE_CORE_UTIL_H
#define FHE_CORE_UTIL_H

#include <boost/config.hpp>
#include <string>
#include <vector>

namespace fhe
{
  namespace core
  {
    #ifndef FHE_ARGS
    #define FHE_ARGS 10
    #endif

    #ifdef BOOST_WINDOWS
      #ifdef FHE_BUILD
        #define FHE_API __declspec( dllexport )
      #else
        #define FHE_API __declspec( dllimport )
      #endif
    #else
      #define FHE_API
    #endif
    
    class Assert
    {
    public:
      static FHE_API void assertNoMsg( bool cond, const char* scond, const char* file, int line );
      static FHE_API void errorMsg( const char* file, int line, const char* fmt, ... );
      static FHE_API void assertMsg( bool cond, const char* scond, const char* file, int line, const char* fmt, ... );
    private:
      Assert();
      ~Assert();
    };
    
    #define FHE_ASSERT( cond ) ::fhe::core::Assert::assertNoMsg( (cond), #cond, __FILE__, __LINE__ );
    #define FHE_ERROR( fmt, ... ) ::fhe::core::Assert::errorMsg( __FILE__, __LINE__, fmt, ##__VA_ARGS__ ); throw;
    #define FHE_ASSERT_MSG( cond, fmt, ... ) ::fhe::core::Assert::assertMsg( (cond), #cond, __FILE__, __LINE__, fmt, ##__VA_ARGS__ );
    
    class Log
    {
    public:
      static FHE_API void log( const char* fmt, ... );
    private:
      Log();
      ~Log();
    };
    
    #define FHE_LOG( fmt, ... ) ::fhe::core::Log::log( fmt, ##__VA_ARGS__ );
    
    class StringUtil
    {
    public:
      static FHE_API std::string replace( const std::string& s, 
                                          const std::string& from, 
                                          const std::string& to );
      static FHE_API std::vector< std::string > split( const std::string& s,
                                                       const std::string& delims );
    private:
      StringUtil();
      ~StringUtil();
    };
  }
}


#endif
